using System;
using System.Text;
using System.Collections.Generic;

enum Opcodes
{
    NONE        = 0,
    MSG_ONE     = 1,
    MSG_TWO     = 2,
}

class PacketManager
{
    private List<byte> buffer = new List<byte>();
    private Packet currentPacket = new Packet();

    public void ReadData(byte[] bytes)
    {
        buffer.AddRange(bytes);

        while (true)
        {
            if (buffer.Count >= 1 && currentPacket.Opcode == Opcodes.NONE)
            {
                currentPacket.Opcode = (Opcodes)buffer[0];
            }
            if (buffer.Count >= 3 && currentPacket.Length == 0)
            {
                currentPacket.Length = buffer[1];
                currentPacket.Length <<= 8;
                currentPacket.Length |= buffer[2];
            }

            if (buffer.Count >= currentPacket.Length + 3)
            {
                byte[] data = new byte[currentPacket.Length];
                Array.Copy(buffer.ToArray(), 3, data, 0, currentPacket.Length);
                currentPacket.Data = data;

                buffer.RemoveRange(0, currentPacket.Length + 3);
                Process(currentPacket);
                currentPacket = new Packet();
            }
            else
            {
                break;
            }
        }
    }

    public void Process(Packet packet)
    {
        switch (packet.Opcode)
        {
            case Opcodes.MSG_ONE:
                handleOne(packet.Data);
                break;

            case Opcodes.MSG_TWO:
                handleTwo(packet.Data);
                break;

            default:
                throw new Exception("Invalid operation code " + packet.Opcode.ToString());
        }
    }

    private void handleOne(byte[] data)
    {
        Console.WriteLine("handleOne: {0}", Encoding.UTF8.GetString(data));
    }

    private void handleTwo(byte[] data)
    {
    }
}
